package com.example.getfollowlist.service

import android.accessibilityservice.AccessibilityService
import android.accessibilityservice.GestureDescription
import android.graphics.Path
import android.graphics.Rect
import android.os.Handler
import android.util.Log
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.Toast
import java.io.File
import java.io.FileWriter
import java.text.SimpleDateFormat
import java.util.*

/**
 * 关注列表采集任务类
 * 
 * 负责从抖音关注列表页面采集用户名并保存到文件。
 * 主要功能包括：
 * 1. 遍历页面元素获取用户名
 * 2. 执行滚动操作以加载更多内容
 * 3. 检测"发现朋友"标记以确定列表结束
 * 4. 将采集到的用户名保存到文件
 */
class FollowListTask(
    private val service: AccessibilityService,
    private val handler: Handler
) {
    // 任务状态控制
    private var isCollecting = false
    private var lastScrollTime = 0L
    private val SCROLL_DELAY = 1500L
    private var retryCount = 0
    private val MAX_RETRY = 3

    // 数据存储
    private val followingList = mutableSetOf<String>()
    private var lastFoundNames = mutableSetOf<String>()

    companion object {
        private const val TAG = "GetFollowList"
        private const val DISCOVER_FRIENDS_TEXT = "发现朋友"
    }

    /**
     * 启动关注列表采集任务
     * 初始化状态并开始采集过程
     */
    fun start() {
        Log.d(TAG, "准备开始采集关注列表")
        isCollecting = true
        followingList.clear()
        lastFoundNames.clear()
        retryCount = 0
        lastScrollTime = 0L
        Log.d(TAG, "开始采集关注列表")
        Toast.makeText(service, "开始采集关注列表", Toast.LENGTH_SHORT).show()
        
        // 立即开始第一次采集
        val root = service.rootInActiveWindow
        if (root != null) {
            Log.d(TAG, "执行第一次采集")
            handleEvent(AccessibilityEvent(), root)
        } else {
            Log.e(TAG, "无法获取根节点，采集失败")
        }
        
        // 设置定时器，每2秒检查一次
        handler.postDelayed(object : Runnable {
            override fun run() {
                if (isCollecting) {
                    val currentRoot = service.rootInActiveWindow
                    if (currentRoot != null) {
                        Log.d(TAG, "执行定时采集")
                        handleEvent(AccessibilityEvent(), currentRoot)
                    } else {
                        Log.e(TAG, "定时采集时无法获取根节点")
                    }
                    handler.postDelayed(this, 2000)
                }
            }
        }, 2000)
    }

    /**
     * 处理无障碍事件
     * 根据页面状态执行采集或滚动操作
     */
    fun handleEvent(event: AccessibilityEvent, root: AccessibilityNodeInfo) {
        if (!isCollecting) return

        val currentTime = System.currentTimeMillis()
        if (currentTime - lastScrollTime < SCROLL_DELAY) return

        // 检查是否到达列表底部
        if (hasReachedBottom(root)) {
            Log.d(TAG, "检测到'发现朋友'标记，采集完成")
            saveFollowingList()
            isCollecting = false
            return
        }

        // 采集当前页面的用户名
        handleFollowingList(root)
    }

    /**
     * 处理关注列表内容
     * 采集用户名并决定是否需要滚动加载更多
     */
    private fun handleFollowingList(root: AccessibilityNodeInfo) {
        lastFoundNames.clear()
        var foundNewNames = false

        try {
            // 查找已关注按钮的父节点以获取用户名
            val followedButtons = root.findAccessibilityNodeInfosByText("已关注")
            Log.d(TAG, "找到 ${followedButtons.size} 个'已关注'按钮")

            for (button in followedButtons) {
                var parent = button.parent
                val textsInParent = mutableListOf<String>()

                // 向上遍历三层父节点收集文本
                repeat(3) { level ->
                    if (parent != null) {
                        collectTexts(parent, textsInParent)
                        parent = parent.parent
                    }
                }

                // 过滤并处理收集到的文本
                val validNames = textsInParent.filter { text ->
                    text.length >= 2 && // 用户名通常至少2个字符
                    !text.contains("关注") && // 排除按钮文本
                    !text.contains("粉丝") &&
                    !text.contains("作品") &&
                    !text.contains("获赞") &&
                    !text.contains("动态")
                }

                // 选择最可能的用户名
                validNames.firstOrNull()?.let { name ->
                    if (followingList.add(name)) {
                        lastFoundNames.add(name)
                        foundNewNames = true
                        Log.d(TAG, "找到新用户: $name")
                    }
                }
            }

            // 根据采集结果决定下一步操作
            if (foundNewNames) {
                Log.d(TAG, "本次采集到 ${lastFoundNames.size} 个新用户")
                retryCount = 0
                performScroll()
            } else if (retryCount < MAX_RETRY) {
                Log.d(TAG, "未找到新用户，重试第 ${retryCount + 1} 次")
                retryCount++
                performScroll()
            } else {
                Log.d(TAG, "达到最大重试次数，结束采集")
                saveFollowingList()
                isCollecting = false
            }
        } catch (e: Exception) {
            Log.e(TAG, "处理关注列表时发生错误: ${e.message}")
        }
    }

    /**
     * 执行滚动操作
     * 计算滚动路径并执行手势
     */
    private fun performScroll() {
        try {
            val displayMetrics = service.resources.displayMetrics
            val screenHeight = displayMetrics.heightPixels

            val scrollPath = Path().apply {
                // 从屏幕底部向上滚动
                moveTo(displayMetrics.widthPixels / 2f, screenHeight * 0.8f)
                lineTo(displayMetrics.widthPixels / 2f, screenHeight * 0.2f)
            }

            val gestureBuilder = GestureDescription.Builder()
            val gesture = gestureBuilder
                .addStroke(GestureDescription.StrokeDescription(scrollPath, 0, 500))
                .build()

            service.dispatchGesture(gesture, null, null)
            lastScrollTime = System.currentTimeMillis()
            Log.d(TAG, "执行滚动操作")
        } catch (e: Exception) {
            Log.e(TAG, "执行滚动操作时发生错误: ${e.message}")
        }
    }

    /**
     * 检查是否到达列表底部
     * 通过查找"发现朋友"文本判断
     */
    private fun hasReachedBottom(root: AccessibilityNodeInfo): Boolean {
        return root.findAccessibilityNodeInfosByText(DISCOVER_FRIENDS_TEXT).isNotEmpty()
    }

    /**
     * 收集节点中的文本内容
     */
    private fun collectTexts(node: AccessibilityNodeInfo, texts: MutableList<String>) {
        try {
            node.text?.toString()?.let { text ->
                if (text.isNotBlank()) {
                    texts.add(text)
                }
            }

            for (i in 0 until node.childCount) {
                node.getChild(i)?.let { child ->
                    collectTexts(child, texts)
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "收集文本时发生错误: ${e.message}")
        }
    }

    /**
     * 保存关注列表到文件
     * 使用时间戳创建文件名，将采集到的用户名写入文件
     */
    private fun saveFollowingList() {
        try {
            if (followingList.isEmpty()) {
                Log.w(TAG, "关注列表为空")
                Toast.makeText(service, "未采集到关注列表", Toast.LENGTH_LONG).show()
                return
            }

            val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
            val fileName = "following_list_$timestamp.txt"
            val file = File(service.getExternalFilesDir(null), fileName)

            FileWriter(file).use { writer ->
                followingList.forEach { name ->
                    writer.write("$name\n")
                }
            }

            Log.d(TAG, "已保存 ${followingList.size} 个用户名到文件: ${file.absolutePath}")
            Toast.makeText(service, "已保存关注列表: ${followingList.size} 个用户", Toast.LENGTH_LONG).show()
        } catch (e: Exception) {
            Log.e(TAG, "保存关注列表时发生错误: ${e.message}")
            Toast.makeText(service, "保存关注列表失败", Toast.LENGTH_LONG).show()
        }
    }
} 
